<?php


namespace app\api\controller;


use app\admin\model\BaseSetting;
use app\common\library\MysicLog;
use app\common\library\wechat\Abonus;
use app\factory\MqFactory;
use think\Db;
use utils\Services;

class DividendBonus extends \think\Controller
{
    /* @var MysicLog $log */
    private $log;

    /**
     * 构造方法
     * @throws \app\common\exception\BaseException
     * @throws \think\exception\DbException
     */
    public function _initialize()
    {
        parent::_initialize();
        $this->log = MysicLog::instance();
    }

    /**
     * 出局处理
     * @return array|bool|mixed
     * @throws \think\exception\DbException
     */
    public function divideBonus(){
        try {
            $this->log->setFilename('dividend/bonus');
            $this->log->info('开始', '用户不分红队列开始');
            $rmq = MqFactory::instance();
            $processMessage = function ($envelope) {
                $msg = $envelope->getBody();
                $params= json_decode($msg,true);
                //获取订单信息
                $order=$this->getOrderInfo($params['orderId']);
                //获取设置信息
                $setting=$this->getWxappSetting($order['wxapp_id']);
                $this->log->info($setting,  '商户设置信息:');
                //获取商户代理的服务费
                $serviceCharge=$this->storeServiceCharge($order['wxapp_id']);
                $this->log->info($serviceCharge,  '代理商分成:');
                //如果用的支付时间在设置的市价那段内
                if ($setting['start_time']<$order['pay_time']){
                    //获取用户openid
                    $openId=$this->getUserOpenId($order['user_id'],$order['wxapp_id']);
                    //写入分红系统平台得信息
                    $this->log->info('开始',  '写入分红系统平台得信息: 开始...');
                    $this->setSystemAccounts($order,$setting,$serviceCharge);
                    $this->log->info('开始',  '写入分红系统平台得信息: 完成');

                    //写入服务商分红信息
                    $this->log->info('开始',  '写入服务商分红信息: 开始...');
                    $this->setOperateCenterAccounts($order,$setting);
                    $this->log->info('开始',  '写入服务商分红信息: 完成');

                    $this->log->info('开始',  '写入商户分红信息:开始..');
                    //未设置分红或是未到分红时间，用户分红为0
                    $this->setStoreAccounts($order,$setting);
                    $this->log->info('开始',  '写入商户分红信息:结束..');

                    //调用分账接口
                    $Abonus=new Abonus($order['wxapp_id']);
                    $req=$Abonus->addReceiver();
                    $this->log->info('开始',  '将服务商添加到 微信端分账接收方结束');
                    if($req['return_code']=='SUCCESS' &&  $req['result_code']=='SUCCESS'){
                        $this->log->info('开始',  '微信端分账接收方结束');
                        sleep(60);
                        $reault=$Abonus->profitSharings($order);
                        $this->log->info('开始',  '微信端分账');
                        if ($reault['return_code']=='SUCCESS' && $reault['result_code']=='SUCCESS'){
                            $this->log->info('开始',  '系统分账结果');
                            //将用户写入分红队列
                            $this->setUserQueue($order,$setting,$openId);
                            $this->log->info('结束', '系统分账结果');
                        }else{
                            $this->log->info('开始', '系统分账失败结果：失败');
                            $this->setSystemAbonus($order['order_no'],$reault['err_code_des']);
                            $this->log->info('结束', '系统分账失败结果：失败');
                        }

                    }else{
                        $this->log->info('结束','将服务商添加到分账接收方失败');
                    }

                }else{
                    //写入分红系统平台得信息
                    $this->log->info('开始',  '写入分红系统平台得信息: 开始...');
                    $this->setSystemAccounts($order,$setting,$serviceCharge);
                    $this->log->info('开始',  '写入分红系统平台得信息: 完成');

                    //写入服务商分红信息
                    $this->log->info('开始',  '写入服务商分红信息: 开始...');
                    $this->setOperateCenterAccounts($order,$setting);
                    $this->log->info('开始',  '写入服务商分红信息: 完成');

                    $this->log->info('开始',  '写入商户分红信息:开始..');
                    //未设置分红或是未到分红时间，用户分红为0
                    $this->setStoreAccounts($order,$setting);
                    $this->log->info('开始',  '写入商户分红信息:结束..');

                    //调用分账接口
                    $Abonus=new Abonus($order['wxapp_id']);
                    $req=$Abonus->addReceiver();
                    $this->log->info('开始',  '将服务商添加到 微信端分账接收方结束');
                    if($req['return_code']=='SUCCESS' &&  $req['result_code']=='SUCCESS'){
                        $this->log->info('开始',  '微信端分账接收方结束');
                        sleep(60);
                        $reault=$Abonus->profitSharings($order);
                        $this->log->info('开始',  '微信端分账');
                        if ($reault['return_code']=='SUCCESS' && $reault['result_code']=='SUCCESS'){
                            return true;
                        }else{
                            $this->log->info('开始', '系统分账失败结果：失败');
                            $this->setSystemAbonus($order['order_no'],$reault['err_code_des']);
                            $this->log->info('结束', '系统分账失败结果：失败');
                        }

                    }else{
                        $this->log->info('结束','将服务商添加到分账接收方失败');
                    }
                }


            };

            $rmq->run($processMessage, 'dividendBonus','dividendBonusLog','dividendBonusLog');

            $this->log->info('结束', '队列结束');

        } catch (Throwable $e) {
            $this->log->info(exceptionLogFormat($e), '期号变更分红队列出局处理抛出异常');

        }


    }


    /**
     *  将系统分红写入数据表
     * @param $setting array 分红信息
     * @param $order array 订单信息
     * @param $service float 抽成比例
     */
    private function setSystemAccounts($order,$setting,$service){

        $this->log->info($order,  '订单信息:');
        $this->log->info($setting,  '商户设置信息:');
        $this->log->info($service,  '代理商分成:');
        //获取系统服务商信息
        $systemConfig=BaseSetting::getItem('wechat');
        $system['account']            =$systemConfig['mch_id'];//服务商商户id
        $system['order_no']           =$order['order_no'];//订单号
        $system['wxapp_id']           =$order['wxapp_id'];//微信小程序内部编号
        $system['abonus']             =bcmul($order['pay_price'],($setting['service_charge']/100),2);//系统平台一共分账可得金额(单位/分)
        $system['amount']             =bcmul($system['abonus'],(1-$service),4);//分红金额(单位/分)
        $system['description']        ='分账给系统服务商';
        $system['payment']            =$order['pay_price'];//实际支付总金额(单位/分)
        $system['transaction_id']     =$order['transaction_id'];//微信内部订单
        $system['status']             =0;//结算状态 0待分账 1已分账 2分账失败
        $system['create_time']        =time();//写入时间
        $system['periods_num']        =$setting['periods_num'];//期号
        return db('divide_system')->insert($system);
    }

    /**
     * @param $order array 订单信息
     * @param $setting  array   分红设置
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function setOperateCenterAccounts($order,$setting){
        //获取服务商的id
        $agentId=db('wxapp')->where(['wxapp_id'=>$order['wxapp_id']])->value('agent_id');

        if ($agentId!==0){
            $agentList=collection(db('agent')->where(['is_recycle'=>0,'status'=>1,'is_delete'=>0])->order('agent_id asc')->select())->toArray();//合伙人层级
            if (!empty($agentList)){
                $tree =Services::instance();
                $tree->init($agentList, 'recommend_id');
                $agentData=$tree->getParents($agentId,true);
                $agentCount=count($agentData);

                $agentDividendsDataArray=[];
                if($agentCount==1){
                    $agentDividendsDataArray['name']          = $agentData[0]['company_name'];
                    $agentDividendsDataArray['type']          = 1;
                    $agentDividendsDataArray['agent_id']      = $agentData[0]['agent_id'];
                    $agentDividendsDataArray['amount']        = bcmul(($agentData[0]['service_charge']/100),($order['pay_price']*($setting['service_charge']/100)),4);
                    $agentDividendsDataArray['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                    $agentDividendsDataArray['order_no']      = $order['order_no'];//订单号
                    $agentDividendsDataArray['payment']       = $order['pay_price'];//订单实际支付金额
                    $agentDividendsDataArray['transaction_id']= $order['transaction_id'];
                    $agentDividendsDataArray['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                    $agentDividendsDataArray['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                    $agentDividendsDataArray['create_time']   = time();//写入时间（支付时间）
                    $agentDividendsDataArray['periods_num']   = $setting['periods_num'];//期号
                    db('divide_service')->insert($agentDividendsDataArray);
                }elseif ($agentCount==2){
                    $agentDividendsDataArray[0]['name']          = $agentData[0]['company_name'];
                    $agentDividendsDataArray[0]['type']          = 1;
                    $agentDividendsDataArray[0]['agent_id']      = $agentData[0]['agent_id'];
                    $agentDividendsDataArray[0]['amount']        = bcmul((($agentData[0]['service_charge']-$agentData[1]['service_charge'])/100),bcmul($order['pay_price'],($setting['service_charge']/100),4),4);
                    $agentDividendsDataArray[0]['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                    $agentDividendsDataArray[0]['order_no']      = $order['order_no'];//订单号
                    $agentDividendsDataArray[0]['payment']       = $order['pay_price'];//订单实际支付金额
                    $agentDividendsDataArray[0]['transaction_id']= $order['transaction_id'];
                    $agentDividendsDataArray[0]['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                    $agentDividendsDataArray[0]['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                    $agentDividendsDataArray[0]['create_time']   = time();//写入时间（支付时间）
                    $agentDividendsDataArray[0]['periods_num']   = $setting['periods_num'];//期号
                    if($agentData[1]['type']==1){
                        //分账给运营商
                        $agentDividendsDataArray[1]['name']          = $agentData[1]['company_name'] ? $agentData[1]['company_name'] : $agentData[1]['real_name'];
                        $agentDividendsDataArray[1]['type']          = 2;
                        $agentDividendsDataArray[1]['agent_id']      = $agentData[1]['agent_id'];
                        $agentDividendsDataArray[1]['amount']        = bcmul(($agentData[1]['service_charge']/100),bcmul($order['pay_price'],($setting['service_charge']/100),4),4);
                        $agentDividendsDataArray[1]['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                        $agentDividendsDataArray[1]['order_no']      = $order['order_no'];//订单号
                        $agentDividendsDataArray[1]['payment']       = $order['pay_price'];//订单实际支付金额
                        $agentDividendsDataArray[1]['transaction_id']= $order['transaction_id'];
                        $agentDividendsDataArray[1]['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                        $agentDividendsDataArray[1]['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                        $agentDividendsDataArray[1]['create_time']   = time();//写入时间（支付时间）
                        $agentDividendsDataArray[1]['periods_num']   = $setting['periods_num'];//期号
                    }elseif ($agentData[1]['type']==2){
                        //分账给合伙人
                        $agentDividendsDataArray[1]['name']          = $agentData[1]['real_name'];
                        $agentDividendsDataArray[1]['type']          =3;
                        $agentDividendsDataArray[1]['agent_id']      =$agentData[1]['agent_id'];
                        $agentDividendsDataArray[1]['amount']        =bcmul(($agentData[1]['service_charge']/100),bcmul($order['pay_price'],($setting['service_charge']/100),4),4);
                        $agentDividendsDataArray[1]['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                        $agentDividendsDataArray[1]['order_no']      = $order['order_no'];//订单号
                        $agentDividendsDataArray[1]['payment']       = $order['pay_price'];//订单实际支付金额
                        $agentDividendsDataArray[1]['transaction_id']= $order['transaction_id'];
                        $agentDividendsDataArray[1]['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                        $agentDividendsDataArray[1]['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                        $agentDividendsDataArray[1]['create_time']   = time();//写入时间（支付时间）
                        $agentDividendsDataArray[1]['periods_num']   = $setting['periods_num'];//期号
                    }
                    db('divide_service')->insertAll($agentDividendsDataArray);

                }elseif($agentCount==3){
                    $agentDividendsDataArray[0]['name']          = $agentData[0]['company_name'];
                    $agentDividendsDataArray[0]['type']          = 1;
                    $agentDividendsDataArray[0]['agent_id']      = $agentData[0]['agent_id'];
                    $agentDividendsDataArray[0]['amount']        = bcmul((($agentData[0]['service_charge']-$agentData[1]['service_charge'])/100),bcmul($order['pay_price'],($setting['service_charge']/100),4),4);
                    $agentDividendsDataArray[0]['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                    $agentDividendsDataArray[0]['order_no']      = $order['order_no'];//订单号
                    $agentDividendsDataArray[0]['payment']       = $order['pay_price'];//订单实际支付金额
                    $agentDividendsDataArray[0]['transaction_id']= $order['transaction_id'];
                    $agentDividendsDataArray[0]['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                    $agentDividendsDataArray[0]['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                    $agentDividendsDataArray[0]['create_time']   = time();//写入时间（支付时间）
                    $agentDividendsDataArray[0]['periods_num']   = $setting['periods_num'];//期号

                    $agentDividendsDataArray[1]['name']          = $agentData[1]['company_name'] ? $agentData[1]['company_name'] : $agentData[1]['real_name'];
                    $agentDividendsDataArray[1]['type']          = 2;
                    $agentDividendsDataArray[1]['agent_id']      = $agentData[1]['agent_id'];
                    $agentDividendsDataArray[1]['amount']        = bcmul((($agentData[1]['service_charge']-$agentData[2]['service_charge'])/100),bcmul($order['pay_price'],($setting['service_charge']/100),4),4);
                    $agentDividendsDataArray[1]['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                    $agentDividendsDataArray[1]['order_no']      = $order['order_no'];//订单号
                    $agentDividendsDataArray[1]['payment']       = $order['pay_price'];//订单实际支付金额
                    $agentDividendsDataArray[1]['transaction_id']= $order['transaction_id'];
                    $agentDividendsDataArray[1]['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                    $agentDividendsDataArray[1]['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                    $agentDividendsDataArray[1]['create_time']   = time();//写入时间（支付时间）
                    $agentDividendsDataArray[1]['periods_num']   = $setting['periods_num'];//期号


                    $agentDividendsDataArray[2]['name']          = $agentData[2]['real_name'];
                    $agentDividendsDataArray[2]['type']          = 3;
                    $agentDividendsDataArray[2]['agent_id']      = $agentData[2]['agent_id'];
                    $agentDividendsDataArray[2]['amount']        = bcmul(($agentData[2]['service_charge']/100),bcmul($order['pay_price'],($setting['service_charge']/100),4),4);
                    $agentDividendsDataArray[2]['abonus']        = bcmul($order['pay_price'],($setting['service_charge']/100),2);//参与分账金额
                    $agentDividendsDataArray[2]['order_no']      = $order['order_no'];//订单号
                    $agentDividendsDataArray[2]['payment']       = $order['pay_price'];//订单实际支付金额
                    $agentDividendsDataArray[2]['transaction_id']= $order['transaction_id'];
                    $agentDividendsDataArray[2]['wxapp_id']      = $order['wxapp_id'];//内部微信小程序编号
                    $agentDividendsDataArray[2]['status']        = 0;//状态（0，未分账，1.已分账，2.分账失败）
                    $agentDividendsDataArray[2]['create_time']   = time();//写入时间（支付时间）
                    $agentDividendsDataArray[2]['periods_num']   = $setting['periods_num'];//期号
                    db('divide_service')->insertAll($agentDividendsDataArray);
                }

            }
        }


    }

    /**
     *   将商户的分红金额入库
     * @param $order  array 订单信息
     * @param $setting array 分红信息
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function setStoreAccounts($order,$setting){

        $storeConfig=db('wxapp')->where('wxapp_id',$order['wxapp_id'])->find();

        $store['account']            =$storeConfig['mchid'];//服务商商户id
        $store['order_no']           =$order['order_no'];//订单号
        $store['wxapp_id']           =$order['wxapp_id'];//微信小程序内部编号
        $store['amount']             = bcsub($order['pay_price'], bcmul($order['pay_price'], ($setting['service_charge']/100),2),2);
        $store['agent_id']           = $storeConfig['agent_id'];
        $store['payment']            =$order['pay_price'];//实际支付总金额(单位/分)
        $store['transaction_id']     =$order['transaction_id'];//微信内部订单
        $store['status']             =0;//结算状态 0待分账 1已分账 2分账失败
        $store['create_time']        =time();//写入时间
        $store['periods_num']        =$setting['periods_num'];//期号
        db('divide_store')->insert($store);
    }

    //用户入分红队列
    private function setUserQueue($order,$setting,$openId){
        //用户分红上限
        $topLimit = bcmul(($setting['upline']/100),$order['pay_price'],2);
        //用户出局时间
        $finishTime=time()+($setting['term']*24*60*60);
        $data=[
            'user_id'=>$order['user_id'],
            'account'=>$openId,
            'order_no'=>$order['order_no'],
            'wxapp_id'=>$order['wxapp_id'],
            'payment' =>$order['pay_price'],
            'periods_num'=>$setting['periods_num'],
            'transaction_id'=>$order['transaction_id'],
            'balance' =>$topLimit,
            'top_limit'=>$topLimit,
            'total_abonus'=>0,
            'type'=>0,
            'times'=>0,
            'create_time'=>time(),
            'update_time'=>time(),
            'reward_money'=>0,
            'refund_money'=>0,
            'finish_time'=>$finishTime,
            'small_change'=>0
        ];
        db('divide_receives')->insert($data);
    }

    /**
     * 分账失败
     * @param $orderNo
     * @param $reason
     */
    private function setSystemAbonus($orderNo,$reason){
        db('divide_system')->where('order_no',$orderNo)->setField(['status'=>2,'fail_reason'=>$reason]);
        db('divide_store')->where('order_no',$orderNo)->setField(['status'=>2,'fail_reason'=>$reason]);
        db('divide_service')->where('order_no',$orderNo)->setField(['status'=>2,'fail_reason'=>$reason]);
    }

    /**
     *  获取订单信息
     * @param $orderId
     * @return array|bool|false|\PDOStatement|string|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getOrderInfo($orderId){
        return db('order')->where('order_id',$orderId)->find();
    }

    /**
     *  获取设置信息
     * @param $wxappId
     * @return array|bool|false|\PDOStatement|string|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getWxappSetting($wxappId){
        return  db('wxapp_setting')->where('wxapp_id',$wxappId)->find();
    }

    /**
     * 获取用户的open_id
     * @param $userId int 用户id
     * @param $wxappId int 微信id
     * @return bool|float|mixed|string|null
     */

    private function getUserOpenId($userId,$wxappId){
        return db('user')->where(['user_id'=>$userId,'wxapp_id'=>$wxappId])->value('open_id');
    }


    private function storeServiceCharge($wxappId){
        //获取商户的代理id
        $agentId=db('wxapp')->where(['wxapp_id'=>$wxappId])->value('agent_id');
        $agentList=collection(db('agent')->where(['is_recycle'=>0,'status'=>1,'is_delete'=>0])->order('agent_id asc')->select())->toArray();//合伙人层级
        if (!empty($agentList)) {
            $tree = Services::instance();
            $tree->init($agentList, 'recommend_id');
            $agentData = $tree->getParents($agentId,true);
            $service=$agentData[0]['service_charge']/100;
            return $service;
        }

    }
}